π EKS IRSA (IAM Roles for Service Accounts) β S3 ReadβOnly Access Guide
This guide shows how to securely allow a Kubernetes pod running on Amazon EKS to read data from an S3 bucket using IAM Roles for Service Accounts (IRSA) β without hardβcoding AWS credentials. π
πͺ Step 1: Get Your OIDC Provider for EKSβ
First, find the OIDC issuer URL for your EKS cluster:
aws eks describe-cluster \
--name <your-cluster-name> \
--query "cluster.identity.oidc.issuer" \
--output text
π€ Output example:
https://oidc.eks.me-south-1.amazonaws.com/id/ABCDEF1234567890
π Verify OIDC Provider Exists in IAMβ
aws iam list-open-id-connect-providers | grep ABCDEF1234567890
β If you see output β OIDC is already configured
β If you donβt see it β create it using eksctl
eksctl utils associate-iam-oidc-provider \
--cluster <your-cluster-name> \
--approve
πͺ Step 2: Create an IAM Policy for S3 Accessβ
Create a policy file named s3-access-policy.json:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:ListBucket"],
"Resource": "arn:aws:s3:::aiops-loadtest-reports"
},
{
"Effect": "Allow",
"Action": ["s3:GetObject"],
"Resource": "arn:aws:s3:::aiops-loadtest-reports/*"
}
]
}
π‘οΈ Scope:
- Readβonly access
- Only for one bucket
β Create the IAM Policyβ
aws iam create-policy \
--policy-name AIOpsLoadTestS3Access \
--policy-document file://s3-access-policy.json
π Save the Policy ARN from the output β youβll need it next.
πͺ Step 3: Create an IAM Role for the Kubernetes Service Accountβ
The easiest and safest way is using eksctl:
eksctl create iamserviceaccount \
--name loadtest-viewer-sa \
--namespace default \
--cluster <your-cluster-name> \
--attach-policy-arn arn:aws:iam::<your-account-id>:policy/AIOpsLoadTestS3Access \
--approve \
--override-existing-serviceaccounts
β What This Doesβ
- π§Ύ Creates a Kubernetes ServiceAccount:
loadtest-viewer-sa - π Creates an IAM Role with trust to EKS OIDC
- π Attaches the S3 readβonly policy
- πͺ Automatically annotates the ServiceAccount
πͺ Step 4: Reference the Service Account in Deployment YAMLβ
Update your Deployment manifest to use the ServiceAccount:
apiVersion: apps/v1
kind: Deployment
metadata:
name: loadtest-viewer
spec:
replicas: 1
selector:
matchLabels:
app: loadtest-viewer
template:
metadata:
labels:
app: loadtest-viewer
spec:
serviceAccountName: loadtest-viewer-sa # π IRSA enabled here
containers:
- name: loadtest-viewer
image: <your-ecr-repo-url>:latest
ports:
- containerPort: 8080
env:
- name: AWS_REGION
value: "me-south-1"
- name: S3_BUCKET
value: "aiops-loadtest-reports"
π« No access keys required
πͺ Step 5: Deploy the Applicationβ
kubectl apply -f deployment.yaml
Verify:
kubectl get pods
πͺ Step 6: Verify the IAM Role Inside the Podβ
Exec into the running pod:
kubectl exec -it <pod-name> -- bash
Check if AWS credentials are injected automatically:
curl 169.254.170.2$AWS_CONTAINER_CREDENTIALS_RELATIVE_URI
π€ You should see temporary credentials (AccessKeyId, Token, Expiration).
π§ͺ Step 7: Test S3 Access from Inside the Podβ
If AWS CLI is installed:
aws s3 ls s3://aiops-loadtest-reports
Or using SDK in your app:
- β List objects
- β Download reports
- β Upload or delete (blocked by policy)
π§ Common Troubleshootingβ
β AccessDenied
- Check ServiceAccount name
- Verify IAM policy attachment
- Ensure pod is restarted after SA creation
β No credentials found
- OIDC provider missing
- Wrong cluster name
π Final Summaryβ
| Component | Purpose |
|---|---|
| π IRSA | Secure AWS access without secrets |
| πͺ OIDC Provider | Trust between EKS & IAM |
| π§Ύ IAM Policy | Fineβgrained S3 permissions |
| π§βπ» ServiceAccount | Identity for pods |
| π¦ Pod | Uses AWS permissions safely |
β This setup is productionβgrade, secure, and AWSβrecommended.